﻿/*=================================================================================================
// <copyright company="AltaModa Technologies, LLC">
//	Copyright (c) AltaModa Technologies, LLC. All rights reserved.
//	http://www.AltaModaTech.com/
// </copyright>
// 
//	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
//	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
//	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
//	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
//	CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
//	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
//	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
//	OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
//	POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================*/

using System;
using System.Web.Security;

namespace AMT.Web.Security
{
	public class LogicalOrRoleProvider<TProvider1, TProvider2> : System.Web.Security.RoleProvider
		where TProvider1 : RoleProvider
		where TProvider2 : RoleProvider
	{
		#region Private member data
		private TProvider1 m_provider1;
		private TProvider2 m_provider2;
		#endregion

		public LogicalOrRoleProvider(TProvider1 provider1, TProvider2 provider2)
		{
			if (null == provider1 || null == provider2) throw new ArgumentNullException();

			m_provider1 = provider1;
			m_provider2 = provider2;
		}


		public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
		{
			base.Initialize(name, config);
			m_provider1.Initialize(name, config);
			m_provider2.Initialize(name, config);
		}


		public override string Description
		{
			get
			{
				return "AMT.Web.Security.LogicalOrRoleProvider";
			}
		}


		public override string ApplicationName { get; set; }

		/// <summary>
		/// Finds combined set of users from both RoleProviders
		/// </summary>
		/// <param name="roleName"></param>
		/// <param name="usernameToMatch"></param>
		/// <returns>User names in role combined from both RoleProviders; may include duplicates</returns>
		public override string[] FindUsersInRole(string roleName, string usernameToMatch)
		{
			string[] usersFoundIn1 = m_provider1.FindUsersInRole(roleName, usernameToMatch);
			string[] usersFoundIn2 = m_provider2.FindUsersInRole(roleName, usernameToMatch);

			string[] usersFound = new string[usersFoundIn1.Length + usersFoundIn2.Length];
			usersFoundIn1.CopyTo(usersFound, 0);
			usersFoundIn2.CopyTo(usersFound, usersFoundIn1.Length);

			return usersFound;
		}

		/// <summary>
		/// Returns all role names combined from both RoleProviders
		/// </summary>
		/// <returns>Role names combined from both RoleProviders; may include duplicates</returns>
		public override string[] GetAllRoles()
		{
			string[] usersIn1 = m_provider1.GetAllRoles();
			string[] usersIn2 = m_provider2.GetAllRoles();

			string[] users = new string[usersIn1.Length + usersIn2.Length];
			usersIn1.CopyTo(users, 0);
			usersIn2.CopyTo(users, usersIn1.Length);

			return users;
		}

		/// <summary>
		/// Gets user's roles combined from each RoleProvider
		/// </summary>
		/// <param name="username"></param>
		/// <returns>User's roles from each RoleProvider; may include duplicates</returns>
		public override string[] GetRolesForUser(string username)
		{
			string[] rolesFoundIn1 = m_provider1.GetRolesForUser(username);
			string[] rolesFoundIn2 = m_provider2.GetRolesForUser(username);

			string[] rolesFound = new string[rolesFoundIn1.Length + rolesFoundIn2.Length];
			rolesFoundIn1.CopyTo(rolesFound, 0);
			rolesFoundIn2.CopyTo(rolesFound, rolesFoundIn1.Length);

			return rolesFound;
		}

		/// <summary>
		/// Returns user names in the role combined from each RoleProvider
		/// </summary>
		/// <param name="roleName"></param>
		/// <returns>User names in the role from each RoleProvider; may include duplicates</returns>
		public override string[] GetUsersInRole(string roleName)
		{
			string[] usersFoundIn1 = m_provider1.GetUsersInRole(roleName);
			string[] usersFoundIn2 = m_provider2.GetUsersInRole(roleName);

			string[] usersFound = new string[usersFoundIn1.Length + usersFoundIn2.Length];
			usersFoundIn1.CopyTo(usersFound, 0);
			usersFoundIn2.CopyTo(usersFound, usersFoundIn1.Length);

			return usersFound;
		}

		/// <summary>
		/// Determines whether either RoleProvider reports user is role. The second RoleProvider
		/// is not used when the first RoleProvider indicates user is in the role.
		/// </summary>
		/// <param name="username"></param>
		/// <param name="roleName"></param>
		/// <returns>True if user is in role; otherwise false.</returns>
		public override bool IsUserInRole(string username, string roleName)
		{
			return (m_provider1.IsUserInRole(username, roleName) || m_provider2.IsUserInRole(username, roleName));
		}

		/// <summary>
		/// Determines whether the role exists in either RoleProvider.  The second RoleProvider
		/// is not used when the first RoleProvider indicates that the role exists.
		/// </summary>
		/// <param name="roleName"></param>
		/// <returns>True if role exists in either RoleProvider; otherwise false.</returns>
		public override bool RoleExists(string roleName)
		{
			return (m_provider1.RoleExists(roleName) || m_provider2.RoleExists(roleName));
		}

		#region Unimplemented RoleProvider methods
		public override void AddUsersToRoles(string[] usernames, string[] roleNames)
		{
			throw new NotImplementedException();
		}

		public override void CreateRole(string roleName)
		{
			throw new NotImplementedException();
		}

		public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
		{
			throw new NotImplementedException();
		}

		public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
		{
			throw new NotImplementedException();
		}
		#endregion
	}
}
